package com.alibaba.citrus.cr.mn.order.center.facade.function.convert;

import com.alibaba.citrus.cr.common.constant.SaleOrderConstants;
import com.alibaba.citrus.cr.common.enums.GeneralStatusEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderChannelEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderReasonEnum;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.function.dataobject.AtomOrderDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONValidator;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.epoch.app.crb2btradecenter.domain.order.model.Order;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.mnordercenter.model.dto.SalesOrderAtomQueryDetailResponse;
import com.epoch.app.mnordercenter.model.dto.SalesOrderAtomQueryResponse;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import static com.alibaba.citrus.cr.common.constant.OrderFeaturesKey.*;

/**
 * @author zhangxiaorui
 * @ClassName AtomOrderDOToSalesOrderAtomQueryResponseConvertor
 * @description: TODO
 * @date 2023/04/27 13:28
 * @version: 1.0
 */
public class AtomOrderDOToSalesOrderAtomQueryResponseConvertor {

    private static final Log log = Log.getLogger(AtomOrderDOToSalesOrderAtomQueryResponseConvertor.class);

    public static List<SalesOrderAtomQueryResponse> convert(List<AtomOrderDO> atomOrderDoList) {
        if(CollectionUtils.isEmpty(atomOrderDoList)) {
            return Lists.newArrayList();
        }
        List<SalesOrderAtomQueryResponse> responseList = Lists.newArrayList();
        for (AtomOrderDO atomOrderDO : atomOrderDoList) {
            Order order = atomOrderDO.getOrder();
            List<OrderLine> orderLines = atomOrderDO.getOrderLines();
            SalesOrderAtomQueryResponse orderResp = convertOrder(order);
            orderResp.setOrderDetails(convertOrderLine(orderLines));
            responseList.add(orderResp);
        }
        // 针对字段null处理为空字符串""，空List转为[]
        String jsonArrString = JSONArray.toJSONString(responseList, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullListAsEmpty);
        responseList = JSONArray.parseArray(jsonArrString, SalesOrderAtomQueryResponse.class);

        return responseList;
    }

    public static List<SalesOrderAtomQueryResponse> convertForInner(List<AtomOrderDO> atomOrderDoList) {
        if(CollectionUtils.isEmpty(atomOrderDoList)) {
            return Lists.newArrayList();
        }
        List<SalesOrderAtomQueryResponse> responseList = Lists.newArrayList();
        for (AtomOrderDO atomOrderDO : atomOrderDoList) {
            Order order = atomOrderDO.getOrder();
            List<OrderLine> orderLines = atomOrderDO.getOrderLines();
            SalesOrderAtomQueryResponse orderResp = convertOrder(order);
            JSONObject jsonObject = StringUtils.isNotBlank(orderResp.getBizFeatures()) ? JSONObject.parseObject(orderResp.getBizFeatures()) : new JSONObject();
            JSONObject orderFeaturesJsonObject = StringUtils.isNotBlank(order.getFeatures()) ? JSONObject.parseObject(order.getFeatures()) : new JSONObject();
            jsonObject.put("sapReturnMessage", orderFeaturesJsonObject.containsKey("msg") ? orderFeaturesJsonObject.get("msg") : "");
            orderResp.setBizFeatures(jsonObject.toJSONString());
            orderResp.setOrderDetails(convertOrderLine(orderLines));
            responseList.add(orderResp);
        }
        // 针对字段null处理为空字符串""，空List转为[]
        String jsonArrString = JSONArray.toJSONString(responseList, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullListAsEmpty);
        responseList = JSONArray.parseArray(jsonArrString, SalesOrderAtomQueryResponse.class);

        return responseList;
    }

    private static List<SalesOrderAtomQueryDetailResponse> convertOrderLine(List<OrderLine> orderLines) {
        if (CollectionUtils.isEmpty(orderLines)) {
            return Lists.newArrayList();
        }
        List<SalesOrderAtomQueryDetailResponse> responses = Lists.newArrayList();
        for (OrderLine orderLine : orderLines) {
            int unitPrice = StringUtils.isNotBlank(orderLine.getUnitPrice()) ? Integer.parseInt(orderLine.getUnitPrice()) : 0;
            int quantity = orderLine.getQuantity();
            int totalAmount = 0;
            try {
                // 由于带活动的订单shouldPayFee字段会被刷成活动后总金额，所以常规总金额改为通过常规单价计算
                totalAmount = unitPrice * quantity;
            } catch (Exception e) {
                log.error("AtomOrderDOToSalesOrderAtomQueryResponseConvertor#convertOrderLine error", e);
            }

            SalesOrderAtomQueryDetailResponse response = SalesOrderAtomQueryDetailResponse.builder()
                    .closeCode(orderLine.getRefuseReasonCode())
                    .closeMsg(orderLine.getRefuseReasonName())
                    .deliveryFactoryCode(orderLine.getDeliveryFactoryCode())
                    .deliveryFactoryName(orderLine.getDeliveryFactoryName())
                    .isClose(String.valueOf(orderLine.getClosed()))
                    .isCloseName(GeneralStatusEnum.descByCode(orderLine.getClosed()))
                    .lineNum(orderLine.getSerialNumber())
                    .buyItemNo(orderLine.getBuyItemNo())
                    .note(orderLine.getRemark())
                    .outLineNum(orderLine.getOuterOrderLineId())
                    .sourceLineNum(orderLine.getSourceLineNum())
                    //.produceDate(formatDate(orderLine.getProductationTime()))
                    .productBarCode(orderLine.getProductBarCode())
                    .productCode(parseMoneyFromFeatures(orderLine, "productCode", orderLine.getScItemOutCode()))
                    .productName(orderLine.getScItemTitle())
                    .salesUnitCode(orderLine.getSaleUnit())
                    .salesUnitName(orderLine.getSaleUnitName())
                    .stockCode(orderLine.getStockCode())
                    .stockConversionNum(orderLine.getStockConversionNum())
                    .stockName(orderLine.getStockName())
                    .stockUnitCode(orderLine.getInventoryUnitCode())
                    .stockUnitName(orderLine.getInventoryUnit())
                    .unitConversionRelationship(orderLine.getUnitConvert())
                    .unitPrice(String.valueOf(unitPrice))
                    .totalAmount(String.valueOf(totalAmount))
                    .cumulativeDeliveryQuantity(new BigDecimal(StringUtils.defaultString(orderLine.getDeliveryAmount(), "0")).longValue())
                    .cumulativePlanDeliveryQuantity(new BigDecimal(StringUtils.defaultString(orderLine.getCumulativeDeliveryQuantity(), "0")).longValue())
                    .productQuantity((long) quantity)
                    .manualPrice(parseFromFeatures(orderLine, SaleOrderConstants.MANUAL_PRICE, orderLine.getManualPrice()))
                    .manualTotalAmount(parseFromFeatures(orderLine, SaleOrderConstants.MANUAL_TOTAL_AMOUNT, orderLine.getManualTotalAmount()))
                    .activityPrice(orderLine.getActivityPrice())
                    .activityTotalAmount(orderLine.getTotalActivityFee())
                    .activityType(orderLine.getActivityType())
                    .activityId(orderLine.getActivityCode())
                    .activityLineNo(orderLine.getActivityTermId())
                    .status(orderLine.getStatus())
                    .innerProductCode(orderLine.getInnerProductCode())
                    .innerProductName(orderLine.getInnerProductName())
                    .giftFlag(parseFromFeatures(orderLine, SaleOrderConstants.GIFT_FLAG, null))
                    .shippingWarehouseCode(parseFromFeatures(orderLine, "logicWarehouseCode", orderLine.getShippingWarehouseCode()))
                    .shippingWarehouseName(orderLine.getShippingWarehouseName())
                    .bizFeatures(orderLine.getBizFeatures())
                    .confirmQuantity(Objects.isNull(orderLine.getConfirmQuantity()) ? "" : String.valueOf(orderLine.getConfirmQuantity()))
                    .giftQuantity(orderLine.getGiftQuantity())
                    .taxRate(orderLine.getTaxRate())
                    .productationTime(formatDate(orderLine.getProductationTime()))
                    .totalActivityFee(orderLine.getTotalActivityFee())
                    .relationLineNo(orderLine.getRelationLineNo())
                    .cumulativeNoticeQuantity(orderLine.getCumulativeNoticeQuantity())
                    .cumulativeWaitOutboundQuantity(orderLine.getCumulativeWaitOutboundQuantity())
                    .cumulativeReceivedQuantity(orderLine.getCumulativeReceivedQuantity())
                    .sourceUnit(parseFromFeatures(orderLine, "sourceUnit", ""))
                    .sourceQuantity(parseFromFeatures(orderLine, SOURCE_QUANTITY, ""))
                    .sourcePrice(parseFromFeatures(orderLine, SOURCE_PRICE, ""))
                    .receiveStatus(orderLine.getSubStatus())
                    .build();
            // 换算金额(分) -> (元)
            reSetMoneyForNYC(response);

            responses.add(response);
        }
        return responses;
    }

    private static String parseMoneyFromFeatures(OrderLine orderLine, String key, String defaultVal) {
        Map<String, String> featuresMap = JSONObject.parseObject(orderLine.getFeatures(), new TypeReference<Map<String, String>>() {});
        if(MapUtils.isEmpty(featuresMap)) {
            return defaultVal;
        }
        return featuresMap.getOrDefault(key, defaultVal);
    }

    private static String parseFromFeatures(OrderLine orderLine, String key, String defaultVal) {
        Map<String, String> featuresMap = JSONObject.parseObject(orderLine.getFeatures(), new TypeReference<Map<String, String>>() {});
        if(MapUtils.isEmpty(featuresMap)) {
            return defaultVal;
        }
        return featuresMap.getOrDefault(key, defaultVal);
    }

    private static String parseFromFeatures(Order order, String key, String defaultVal) {
        Map<String, String> featuresMap = JSONObject.parseObject(order.getFeatures(), new TypeReference<Map<String, String>>() {});
        if(MapUtils.isEmpty(featuresMap)) {
            return defaultVal;
        }
        return featuresMap.getOrDefault(key, defaultVal);
    }

    /**
     * 金额转换 分转元
     */
    private static void reSetMoneyForNYC(SalesOrderAtomQueryDetailResponse response) {
        response.setUnitPrice(StringUtils.isBlank(response.getUnitPrice()) ? BigDecimal.ZERO.toPlainString() : new BigDecimal(response.getUnitPrice()).divide(new BigDecimal("100"),2, RoundingMode.DOWN).toPlainString());
        response.setTotalAmount(StringUtils.isBlank(response.getTotalAmount()) ? BigDecimal.ZERO.toPlainString() : new BigDecimal(response.getTotalAmount()).divide(new BigDecimal("100"),2, RoundingMode.DOWN).toPlainString());
        response.setManualPrice(StringUtils.isBlank(response.getManualPrice()) ? BigDecimal.ZERO.toPlainString() : new BigDecimal(response.getManualPrice()).divide(new BigDecimal("100"),2, RoundingMode.DOWN).toPlainString());
        response.setManualTotalAmount(StringUtils.isBlank(response.getManualTotalAmount()) ? BigDecimal.ZERO.toPlainString() : new BigDecimal(response.getManualTotalAmount()).divide(new BigDecimal("100"),2, RoundingMode.DOWN).toPlainString());
        response.setActivityPrice(StringUtils.isBlank(response.getActivityPrice()) ? "" : new BigDecimal(response.getActivityPrice()).divide(new BigDecimal("100"),2, RoundingMode.DOWN).toPlainString());
        response.setActivityTotalAmount(StringUtils.isBlank(response.getActivityTotalAmount()) ? BigDecimal.ZERO.toPlainString() : new BigDecimal(response.getActivityTotalAmount()).divide(new BigDecimal("100"),2, RoundingMode.DOWN).toPlainString());
        response.setTotalActivityFee(StringUtils.isBlank(response.getTotalActivityFee()) ? "" : new BigDecimal(response.getTotalActivityFee()).divide(new BigDecimal("100"),2, RoundingMode.DOWN).toPlainString());
    }

    private static SalesOrderAtomQueryResponse convertOrder(Order order) {
        List<String> orderBizTagList = new ArrayList<>();
        if (StringUtils.isNotBlank(order.getOrderBizTag())) {
            String[] orderBizTagArray = order.getOrderBizTag().split(",");
            orderBizTagList = Arrays.asList(orderBizTagArray);
        }
        SalesOrderAtomQueryResponse response = SalesOrderAtomQueryResponse.builder()
                .businessChannel(order.getChannelCode())
                .businessChannelName(order.getChannelName())
                .costCenterCode(order.getCostCenter())
                .costCenterName(order.getCostCenterName())
                .createTime(formatDate(order.getGmtCreate(), DateUtils.DATETIME_FORMAT))
                .creatorCode(parseUserInfoCode(order.getCreator()))
                .creatorName(order.getCreatorName())
                .customerCode(order.getCustomerCode())
                .customerName(order.getCustomerName())
                .customerPurchaseDate(formatDate(order.getCustomerPurchaseDate(), DateUtils.DATE_FORMAT))
                .customerPurchaseOrderNo(order.getCustomerReferenceNo())
                .deliveryMethodCode(order.getTransportModeCode())
                .deliveryMethodName(order.getTransportModeName())
                .expectedDeliveryDate(formatDate(order.getCustomerExpectDate(), DateUtils.DATE_FORMAT))
                .fromSys(order.getFromSys())
                .modifierCode(parseUserInfoCode(order.getModifier()))
                .modifierName(order.getModifierName())
                .modifierTime(formatDate(order.getGmtModified(), DateUtils.DATETIME_FORMAT))
                .note(order.getRemark())
                .orderReasonCode(order.getCreateReason())// TODO
                .orderReasonName(SalesOrderReasonEnum.descByCode(order.getCreateReason()))
                .orderStatus(String.valueOf(order.getStatus()))
                .outOrderNo(order.getOuterOrderId())
                .preOrderNo(order.getPreOrderNo())
                .productGroupCode(order.getProductGroupCode())
                .productGroupName(order.getProductGroupName())
                .salesChannelCode(order.getSaleChannelOutCode())
                .salesChannelName(order.getSaleChannelName())
                .salesDepartmentCode(order.getDepartmentOutCode())
                .salesDepartmentName(order.getDepartmentName())
                .salesOrderNo(order.getOrderBizId())
                .salesOrderType(order.getOrderType())
                .salesOrderTypeName(order.getOrderTypeName())
                .salesOrganizationCode(order.getOrganizationOutCode())
                .salesOrganizationName(order.getOrganizationName())
                .shippingWarehouseCode(order.getWareHouseOutCode())
                .shippingWarehouseName(order.getWareHouseName())
                .shipToPartyCode(order.getReceiveAddressCode())
                .shipToPartyName(order.getReceiveDetailAddress())
                .sourceOrderNo(order.getSourceOrderNo())
                .cashCustomerName(order.getCashCustomerName())
                .businessUnitCode(order.getBisUnitOutCode())
                .businessUnitName(order.getBisUnitName())
                .businessType(order.getBusinessType())
                .bizFeatures(order.getBizFeatures())
                .orderCategoryCode(order.getOrderCategoryCode())
                .orderCategoryName(OrderCategoryEnum.descByCode(order.getOrderCategoryCode()))
                .orderChannelCode(order.getOrderChannelCode())
                .orderChannelName(OrderChannelEnum.descByCode(order.getOrderChannelCode()))
                .receiveWarehouseCode(order.getReceiveWareHouseOutCode())
                .receiveWarehouseName(order.getReceiveWareHouseName())
                .receiveFactoryCode(order.getReceiveFactoryCode())
                .customerGrade(order.getCustomerGrade())
                .customerGroup(order.getCustomerGroup())
                .fulfillmentTypeCode(order.getFulfillmentTypeCode())
                .fulfillmentPriority(order.getFulfillmentPriority())
                .autoFulfillment(order.getAutoFulfillment())
                .orderBizTag(orderBizTagList)
                .receiveStockCode(order.getReceiveStockCode())
                .relatonNo(order.getRelationNo())
                .receiveStatus(order.getSubStatus())
                .kaSystem(parseFromFeatures(order, KA_SYSTEM, ""))
                .kaArea(parseFromFeatures(order, KA_AREA, ""))
                .sourceTime(parseFromFeatures(order, SOURCE_ORDER_TIME, ""))
                .customerGroupName(order.getCustomerGroupName())
                .creatorCode(order.getCreatorCode())
                .creatorName(order.getCreatorName2())
                .modifierCode(order.getModifierCode())
                .modifierName(order.getModifierName2())
                .build();

        return response;
    }

    private static String parseUserInfoCode(String dbCreator) {
        if(StringUtils.isBlank(dbCreator) || !JSONValidator.from(dbCreator).validate()) {
            return dbCreator;
        }
        Map<String, String> creatorInfo = JSONObject.parseObject(dbCreator, new TypeReference<Map<String, String>>() {});
        return creatorInfo.getOrDefault("empId", dbCreator);
    }

    private static String formatDate(Date dte, Object... pattern) {
        if(Objects.nonNull(dte)) {
            return DateUtils.formatDate(dte, pattern);
        }
        return null;
    }
}
